from django.db import models
from tasks.helper import rangdom_str
from django.db.models import Q
from asgiref.sync import sync_to_async


def hash_id():
    return rangdom_str(32)


class Model(models.Model):
    """ 基础模块 """

    @classmethod
    @sync_to_async
    def insert(cls, **kwargs):
        return cls.objects.create(**kwargs)

    @classmethod
    @sync_to_async
    def insert_many(cls, items: list):
        objs = list()
        for item in items:
            objs.append(cls(**item))
        return cls.objects.bulk_create(objs)

    @classmethod
    def y(cls, **kwargs):
        query = kwargs.pop('query', None)
        if query:
            return Q(query | Q(**kwargs))
        else:
            return Q(**kwargs)

    @classmethod
    def query(cls, **kwargs):
        filter = kwargs.pop('filter__', None)
        if filter:
            return cls.objects.filter(filter)
        elif kwargs:
            return cls.objects.filter(cls.y(**kwargs))

    @classmethod
    @sync_to_async
    def query_one(cls, **kwargs):
        return cls.query(**kwargs).first()

    class Meta:
        abstract = True


class TimeMixin(Model):
    """ 时间预定义类 """
    update_at = models.DateTimeField(help_text='更新时间', auto_now=True)
    create_at = models.DateTimeField(help_text='入库时间', auto_now_add=True)

    class Meta:
        abstract = True


class JobMixin(Model):
    """ 工作基础类 """
    ExpireLimit = 60

    class JobState:
        Waiting = 'waiting'
        Running = 'running'
        Error = 'error'
        Expire = 'expire'
        Finished = 'finished'

        @classmethod
        def state_msg(cls, state):
            state_map = {'waiting': '等待执行', 'running': '执行中', 'error': '执行出错',
                         'expire': '执行超时', 'finished': '任务完成'}
            return state_map.get(state, f'未知任务状态({state})')

    name = models.CharField(help_text='工作名称', max_length=60, default='')
    job_hash = models.CharField(help_text='工作ID', max_length=32, default=hash_id)
    message = models.CharField(help_text='工作信息', max_length=200, default='')
    state = models.CharField(help_text='工作状态', max_length=30, default=JobState.Waiting)
    expire_at = models.IntegerField(help_text='超时时间点', null=True, default=None)
    is_hidden = models.BooleanField(help_text='是否隐藏', default=False)

    @sync_to_async
    def update_state(self, state):
        self.state = state
        self.save()

    def running(self):
        return self.update_state(JobMixin.JobState.Running)

    def error_done(self):
        return self.update_state(JobMixin.JobState.Error)

    def expire_done(self):
        return self.update_state(JobMixin.JobState.Expire)

    def finished_done(self):
        return self.update_state(JobMixin.JobState.Finished)

    class Meta:
        abstract = True


class DemoTask(JobMixin, TimeMixin):
    job_name = 'demo'

    url = models.CharField(help_text='url', max_length=200, default='')
    content = models.TextField(help_text='content', default='')

    class Meta:
        db_table = 'demo_task'
